package com.ea.admin.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ea.admin.mapper.*;
import com.ea.admin.pojo.Enum.RoleCode;
import com.ea.admin.pojo.dto.UserInfoDto;
import com.ea.admin.pojo.param.user.AddUserItemParam;
import com.ea.admin.pojo.param.user.UserInfoParam;
import com.ea.admin.pojo.po.*;
import com.ea.admin.pojo.vo.user.UserSimpleInfoVo;
import com.ea.admin.pojo.vo.user.GetUserListVo;
import com.ea.admin.pojo.vo.user.ImportUserVo;
import com.ea.admin.pojo.vo.user.UserImportErrorVo;
import com.ea.admin.pojo.vo.user.UserInfoVo;
import com.ea.admin.service.*;
import com.ea.admin.utils.CustomCellWriteHeightConfig;
import com.ea.admin.utils.CustomCellWriteWeightConfig;
import com.ea.admin.utils.ExcelUtils;
import com.ea.admin.utils.MD5Utils;
import com.ea.common.report.ReportFeign;
import com.ea.common.report.pojo.param.GetReportSimpleInfoVoListParam;
import com.ea.common.report.pojo.param.GetUserReportVoParam;
import com.ea.common.report.pojo.vo.ReportSimpleInfoListVo;
import com.ea.common.report.pojo.vo.UserDetailVo;
import com.ea.common.result.BizException;
import com.ea.common.result.ErrorCode;
import com.ea.common.result.Result;
import com.ea.common.utils.AgeUtils;
import com.ea.common.utils.ParamUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    DepartmentService departmentService;
    @Resource
    PositionService positionService;
    @Resource
    CompanyPermissionService companyPermissionService;
    @Resource
    DeptPermissionService deptPermissionService;
    @Resource
    PermissionService permissionService;
    @Resource
    FileService fileService;
    @Resource
    AdminOperatingLogMapper adminOperatingLogMapper;
    @Resource
    UserInfoMapper userInfoMapper;
    @Resource
    CompanyInfoMapper companyInfoMapper;
    @Resource
    DeptInfoMapper deptInfoMapper;
    @Resource
    PositionInfoMapper positionInfoMapper;
    @Resource
    ReportFeign reportFeign;
    @Resource
    AdminAccountMapper adminAccountMapper;
    @Resource
    DataSourceService dataSourceService;

    @Override
    public GetUserListVo getUserList(Long accountId, List<Long> companyIdList, List<Long> deptIdList, List<Long> positionIdList, String name, Integer page, Integer pageSize) {
        // 获得当前管理员的所有单位id
        PermissionServiceImpl.PermissionList checked = permissionService
                .checkAndRefreshPermissionList(companyIdList, deptIdList, positionIdList, accountId);
        companyIdList = checked.companyIdList;
        deptIdList = checked.deptIdList;
        positionIdList = checked.positionIdList;

        // 查询
        Page<UserInfoDto> userInfoPage = userInfoMapper.selectUserDtoList(
                new Page<>(page, pageSize),
                companyIdList,
                deptIdList,
                positionIdList,
                name);

        GetUserListVo result = new GetUserListVo();
        result.setTotal((int) userInfoPage.getTotal());
        result.setPageSize((int) userInfoPage.getSize());
        result.setCurrent((int) userInfoPage.getCurrent());
        result.setItems(parseUserInfoListToVo(userInfoPage.getRecords()));
        return result;
    }


    private List<UserInfoDto> getUserList(List<Long> companyIdList, List<Long> deptIdList, List<Long> positionIdList) {
        Page<UserInfoDto> page = userInfoMapper.selectUserDtoList(
                new Page<>(1, 50),
                companyIdList,
                deptIdList,
                positionIdList,
                null);
        // 分页查出所有用户
        List<UserInfoDto> userInfoDtoList = page.getRecords();
        for (int i = 2; i <= page.getPages(); i++) {
            userInfoDtoList.addAll(userInfoMapper.selectUserDtoList(
                    new Page<>(i, 50),
                    companyIdList,
                    deptIdList,
                    positionIdList,
                    null).getRecords());
        }
        return userInfoDtoList;
    }
    private static List<UserInfoParam> getSample() {
        List<UserInfoParam> sample = new ArrayList<>();
        UserInfoParam zhangSan = new UserInfoParam();
        zhangSan.setName("示例1：张三");
        zhangSan.setCompanyName("北京市XX有限公司");
        zhangSan.setDeptName("人力资源部");
        zhangSan.setPositionName("人力资源部经理");
        zhangSan.setSex("男");
        zhangSan.setBirthday("1990-07-11");
        zhangSan.setPhotoFileName("张三一寸证件照.jpg");
        sample.add(zhangSan);
        UserInfoParam liSi = new UserInfoParam();
        liSi.setName("示例2：李四");
        liSi.setCompanyName("北京市XX有限公司");
        liSi.setDeptName("财务部");
        liSi.setPositionName("财务部副经理");
        liSi.setSex("女");
        liSi.setBirthday("1992-05-21");
        liSi.setPhotoFileName("34jrn23a.jpg");
        sample.add(liSi);
        return sample;
    }

    private void checkPositionIsCompany(String positionId, String companyId) {
        // 检查只为是否属于此单位
        PositionInfo positionInfo = positionInfoMapper.selectById(positionId);
        if (positionInfo == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_POSITION_NOT_EXISTS);
        }
        if (!positionInfo.getCompanyId().toString().equals(companyId)) {
            throw new BizException(ErrorCode.USER_PERMISSION_ERROR);
        }
    }

    private void checkDeptIsCompany(String deptId, String companyId) {
        // 检查部门是否属于此单位
        DeptInfo deptInfo = deptInfoMapper.selectById(deptId);
        if (deptInfo == null) {
            throw new BizException(ErrorCode.USER_PARAM_ERROR_POSITION_NOT_BELONG_COMPANY);
        }
        if (!deptInfo.getCompanyId().toString().equals(companyId)) {
            throw new BizException(ErrorCode.USER_PARAM_ERROR_DEPT_NOT_BELONG_COMPANY);
        }
    }

    @Override
    public void editUser(Long accountId, Long userId, Long companyId, Long deptId, Long positionId, String photoMd5, String name, String sex, Date birthday) {
        UserInfo userinfo = userInfoMapper.selectById(userId);
        boolean reportNeedChange = false;

        if (userinfo == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ERROR_USER_NOT_EXISTS);
        }
        if (!companyId.equals(userinfo.getCompanyId())) {
            // 检查是否是 有修改前单位的权限
            companyPermissionService.checkCompanyPermission(accountId, userinfo.getCompanyId());
            // 检查是否是 有此单位的权限
            companyPermissionService.checkCompanyPermission(accountId, companyId);
            userinfo.setCompanyId(companyId);
            reportNeedChange = true;
        }
        if (!deptId.equals(userinfo.getDeptId())) {
            // 检查是否是 有修改前单位的权限
            deptPermissionService.checkDeptPermission(accountId, userinfo.getDeptId());
            // 检查是否是 有此单位的权限
            deptPermissionService.checkDeptPermission(accountId, deptId);
            checkDeptIsCompany(deptId.toString(), companyId.toString());

            userinfo.setDeptId(deptId);
            reportNeedChange = true;
        }

        if (!positionId.equals(userinfo.getPositionId())) {
            checkPositionIsCompany(positionId.toString(), companyId.toString());
            userinfo.setPositionId(positionId);
            reportNeedChange = true;
        }

        if (!photoMd5.equals(userinfo.getPhoto())) {
            // 上传用户的人脸识别照片
            //模拟服务接入成功 人脸服务
            Result result = reportFeign.uploadPhoto(photoMd5, userinfo.getUserId().toString(), userinfo.getName());
            if (result.getCode() != ErrorCode.NO_ERROR.getCode()) {
                if (result.getCode() == ErrorCode.TPS_FILE_UPLOAD_NO_FACE_ERROR.getCode()) {
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_NO_FACE_ERROR);
                } else if (result.getCode() == ErrorCode.TPS_FILE_UPLOAD_FACE_NO_CORRECT_ERROR.getCode()) {
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_FACE_NO_CORRECT_ERROR);
                }
                throw new BizException(ErrorCode.TPS_FILE_UPLOAD_ERROR);
            }

            userinfo.setPhoto(photoMd5);
        }

        userinfo.setName(name);
        userinfo.setSex(sex);
        userinfo.setBirthday(birthday);
        userInfoMapper.updateById(userinfo);

        if (reportNeedChange) {
            // 修改用户信息时，需要修改对应的报告信息
            Result result = reportFeign.updateUserInfo(
                    userinfo.getUserId(),
                    userinfo.getCompanyId()
            );
            if (result.getCode() != ErrorCode.NO_ERROR.getCode()) {
                throw new BizException(ErrorCode.valueOf(result.getMsg()));
            }
        }
    }

    @Override
    public void deleteUser(Long accountId, Long userId) {
        UserInfo userinfo = userInfoMapper.selectById(userId);
        if (userinfo == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ERROR_USER_NOT_EXISTS);
        }

        // 检查是否是 有此单位的权限
        companyPermissionService.checkCompanyPermission(accountId, userinfo.getCompanyId());
        // 检查是否是 有此部门的权限
        deptPermissionService.checkDeptPermission(accountId, userinfo.getDeptId());

        // 删除该人员的所有人脸
        Result result = reportFeign.deleteUserFace(userId.toString());
        if (result.getCode() != ErrorCode.NO_ERROR.getCode()) {
            throw new BizException(ErrorCode.valueOf(result.getMsg()));
        }

        userInfoMapper.deleteById(userinfo);
    }

    @Override
    public List<UserSimpleInfoVo> addUser(Long accountId, List<AddUserItemParam> addUserItemParamList) {
        // 获得所有用户的部门和公司信息
        Long adminRoleId = adminAccountMapper.selectById(accountId).getAdminRoleId();
        Set<Long> companyIdSet = new HashSet<>();
        Set<Long> deptIdSet = new HashSet<>();
        addUserItemParamList.forEach(addUserItemParam -> {
            companyIdSet.add(ParamUtil.parseId(addUserItemParam.getCompanyId()));
            deptIdSet.add(ParamUtil.parseId(addUserItemParam.getDeptId()));
        });
        List<Long> companyIdList = new ArrayList<>(companyIdSet);
        List<Long> deptIdList = new ArrayList<>(deptIdSet);

        companyIdList.forEach(companyId -> {
                    // 检查是否是 有此单位的权限
            companyPermissionService.checkCompanyPermission(accountId, companyId);
                }
        );
        if(adminRoleId== RoleCode.DEPT_SUPER_ADMIN.getCode().longValue()||
                adminRoleId== RoleCode.DEPT_ADMIN.getCode().longValue()) {
            deptIdList.forEach(deptId -> {
                // 检查是否是 有此部门的权限
                deptPermissionService.checkDeptPermission(accountId, deptId);
            });
        }

        Map<Long, Integer> companyStatistics = new HashMap<>();
        List<UserInfo> userInfoList = new ArrayList<>();
        StringBuffer sb = new StringBuffer("注册登记人员");
        List<UserSimpleInfoVo>usersList=new ArrayList<>();
        addUserItemParamList.forEach(addUserItemParam -> {

            checkDeptIsCompany(addUserItemParam.getDeptId(), addUserItemParam.getCompanyId());
            checkPositionIsCompany(addUserItemParam.getPositionId(), addUserItemParam.getCompanyId());

            UserInfo userInfo = new UserInfo();
            UserSimpleInfoVo userSimpleInfoVo =new UserSimpleInfoVo();
            Long userId=IdWorker.getId(UserInfo.class);
            userSimpleInfoVo.setUserId(String.valueOf(userId));
            userSimpleInfoVo.setName(addUserItemParam.getName());
            usersList.add(userSimpleInfoVo);
            userInfo.setUserId(userId);
            userInfo.setCompanyId(ParamUtil.parseId(addUserItemParam.getCompanyId()));
            userInfo.setDeptId(ParamUtil.parseId(addUserItemParam.getDeptId()));
            userInfo.setPositionId(ParamUtil.parseId(addUserItemParam.getPositionId()));
            userInfo.setName(addUserItemParam.getName());
            userInfo.setSex(addUserItemParam.getSex());
            userInfo.setSourceId(DataSourceService.DEFAULT_DATA_SOURCE_ID);
            userInfo.setBirthday(addUserItemParam.getBirthday());
            userInfo.setPhoto(addUserItemParam.getPhoto());
            userInfo.setIsDel(0);
            userInfoList.add(userInfo);
            sb.append("“").append(addUserItemParam.getName()).append("”");

            //收集公司对应用户数量
            Long companyId=ParamUtil.parseId(addUserItemParam.getCompanyId());
            if (companyStatistics.containsKey(companyId)) {
                companyStatistics.put(companyId, companyStatistics.get(companyId) + 1);
            } else {
                companyStatistics.put(companyId, 1);
            }

            // 上传用户的人脸识别照片
            // 模拟服务接入成功 人脸服务
            Result result = reportFeign.uploadPhoto(addUserItemParam.getPhoto(), userInfo.getUserId().toString(), userInfo.getName());
            if (!result.isSuccess()) {
                if (result.getCode() == ErrorCode.TPS_FILE_UPLOAD_FACE_NO_CORRECT_ERROR.getCode()) {
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_FACE_NO_CORRECT_ERROR, result.getMsg());
                } else if(result.getCode()==ErrorCode.TPS_FILE_UPLOAD_FACE_EXIST_ERROR.getCode()){
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_FACE_EXIST_ERROR, result.getMsg());
                }else if (result.getCode() == ErrorCode.TPS_FILE_UPLOAD_ERROR.getCode()) {
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_ERROR);
                }
            }
        });
        userInfoMapper.insertBatchSomeColumn(userInfoList);

        // 添加用户时，对应的 company info 的 all count 要 + userInfoList.size()
        companyStatistics.forEach((companyId, count) -> {
            CompanyInfo company = companyInfoMapper.selectCompanyInfoById(companyId);
            company.setAllCount(company.getAllCount() + count);
            companyInfoMapper.updateById(company);
        });
        // 记录日志
        AdminOperatingLog adminOperatingLog = new AdminOperatingLog();
        adminOperatingLog.setAccountId(accountId);
        adminOperatingLog.setContent(sb.toString());
        adminOperatingLog.setOperatingTime(LocalDateTime.now());
        adminOperatingLogMapper.insert(adminOperatingLog);

        return usersList;
    }


    @Override
    public List<UserSimpleInfoVo> addUserFromSystem(Long accountId, String token,List<AddUserItemParam> addUserItemParamList) {
        // 验证token并获取数据源信息
        Long dataSourceId;
        try {
            dataSourceId = dataSourceService.getDataSourceByToken(token);
        } catch (Exception e) {
            throw new BizException(ErrorCode.USER_PARAM_ERROR_TOKEN_INVALID);
        }

        // 获得所有用户的部门和公司信息
        Set<Long> companyIdSet = new HashSet<>();
        Set<Long> deptIdSet = new HashSet<>();
        addUserItemParamList.forEach(addUserItemParam -> {
            companyIdSet.add(ParamUtil.parseId(addUserItemParam.getCompanyId()));
            deptIdSet.add(ParamUtil.parseId(addUserItemParam.getDeptId()));
        });

        // 验证公司和部门是否存在
        companyIdSet.forEach(companyId -> {
            if (!companyPermissionService.checkCompanyExists(companyId)) {
                throw new BizException(ErrorCode.SYSTEM_RESOURCE_COMPANY_NOT_EXISTS);
            }
        });
        deptIdSet.forEach(deptId -> {

            if (!deptPermissionService.checkDepartmentExists(deptId)) {
                throw new BizException(ErrorCode.SYSTEM_RESOURCE_COMPANY_NOT_EXISTS);
            }
        });

        Map<Long, Integer> companyStatistics = new HashMap<>();
        List<UserInfo> userInfoList = new ArrayList<>();
        StringBuffer sb = new StringBuffer("外部系统添加用户");
        List<UserSimpleInfoVo>usersList=new ArrayList<>();
        String dataSourceName = dataSourceService.getDataSourceNameById(dataSourceId);
        addUserItemParamList.forEach(addUserItemParam -> {

            checkDeptIsCompany(addUserItemParam.getDeptId(), addUserItemParam.getCompanyId());
            checkPositionIsCompany(addUserItemParam.getPositionId(), addUserItemParam.getCompanyId());

            UserInfo userInfo = new UserInfo();
            UserSimpleInfoVo userSimpleInfoVo =new UserSimpleInfoVo();
            Long userId=IdWorker.getId(UserInfo.class);
            userSimpleInfoVo.setUserId(String.valueOf(userId));
            userSimpleInfoVo.setName(addUserItemParam.getName());
            userSimpleInfoVo.setSourceName(dataSourceName);
            usersList.add(userSimpleInfoVo);
            userInfo.setUserId(userId);
            userInfo.setCompanyId(ParamUtil.parseId(addUserItemParam.getCompanyId()));
            userInfo.setDeptId(ParamUtil.parseId(addUserItemParam.getDeptId()));
            userInfo.setPositionId(ParamUtil.parseId(addUserItemParam.getPositionId()));
            userInfo.setName(addUserItemParam.getName());
            userInfo.setSourceId(dataSourceId);
            userInfo.setSex(addUserItemParam.getSex());
            userInfo.setBirthday(addUserItemParam.getBirthday());
            userInfo.setPhoto(addUserItemParam.getPhoto());
            userInfo.setIsDel(0);
            userInfoList.add(userInfo);
            sb.append("“").append(addUserItemParam.getName()).append("”");

            //收集公司对应用户数量
            Long companyId=ParamUtil.parseId(addUserItemParam.getCompanyId());
            if (companyStatistics.containsKey(companyId)) {
                companyStatistics.put(companyId, companyStatistics.get(companyId) + 1);
            } else {
                companyStatistics.put(companyId, 1);
            }

            // 上传用户的人脸识别照片
            // 模拟服务接入成功 人脸服务
            Result result = reportFeign.uploadPhoto(addUserItemParam.getPhoto(), userInfo.getUserId().toString(), userInfo.getName());
            if (!result.isSuccess()) {
                if (result.getCode() == ErrorCode.TPS_FILE_UPLOAD_FACE_NO_CORRECT_ERROR.getCode()) {
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_FACE_NO_CORRECT_ERROR, result.getMsg());
                } else if(result.getCode()==ErrorCode.TPS_FILE_UPLOAD_FACE_EXIST_ERROR.getCode()){
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_FACE_EXIST_ERROR, result.getMsg());
                }else if (result.getCode() == ErrorCode.TPS_FILE_UPLOAD_ERROR.getCode()) {
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_ERROR);
                }
            }
        });
        userInfoMapper.insertBatchSomeColumn(userInfoList);

        // 添加用户时，对应的 company info 的 all count 要 + userInfoList.size()
        companyStatistics.forEach((companyId, count) -> {
            CompanyInfo company = companyInfoMapper.selectCompanyInfoById(companyId);
            company.setAllCount(company.getAllCount() + count);
            companyInfoMapper.updateById(company);
        });
        // 记录日志
        AdminOperatingLog adminOperatingLog = new AdminOperatingLog();
        adminOperatingLog.setAccountId(1L);
        adminOperatingLog.setContent( sb.toString());
        adminOperatingLog.setOperatingTime(LocalDateTime.now());
        adminOperatingLogMapper.insert(adminOperatingLog);

        return usersList;
    }


    @Override
    public List<UserSimpleInfoVo> addTempUser(List<AddUserItemParam> addUserItemParamList){
        //临时用户默认管理员身份
        Long accountId=1L;

        // 获得所有用户的部门和公司信息
        Set<Long> companyIdSet = new HashSet<>();
        Set<Long> deptIdSet = new HashSet<>();
        addUserItemParamList.forEach(addUserItemParam -> {
            companyIdSet.add(ParamUtil.parseId(addUserItemParam.getCompanyId()));
            deptIdSet.add(ParamUtil.parseId(addUserItemParam.getDeptId()));
        });
        List<Long> companyIdList = new ArrayList<>(companyIdSet);
        List<Long> deptIdList = new ArrayList<>(deptIdSet);

        companyIdList.forEach(companyId -> {
                    // 检查是否是 有此单位的权限
                    companyPermissionService.checkCompanyPermission(accountId, companyId);
                }
        );
        deptIdList.forEach(deptId -> {
            // 检查是否是 有此部门的权限
            deptPermissionService.checkDeptPermission(accountId, deptId);
        });

        Map<Long, Integer> companyStatistics = new HashMap<>();
        List<UserInfo> userInfoList = new ArrayList<>();
        StringBuffer sb = new StringBuffer("临时人员注册登记");// 待确定
        List<UserSimpleInfoVo>usersList=new ArrayList<>();
        addUserItemParamList.forEach(addUserItemParam -> {

            checkDeptIsCompany(addUserItemParam.getDeptId(), addUserItemParam.getCompanyId());
            checkPositionIsCompany(addUserItemParam.getPositionId(), addUserItemParam.getCompanyId());

            UserInfo userInfo = new UserInfo();
            Long userId=IdWorker.getId(UserInfo.class);
            UserSimpleInfoVo userSimpleInfoVo =new UserSimpleInfoVo();
            userSimpleInfoVo.setUserId(String.valueOf(userId));
            userSimpleInfoVo.setName(addUserItemParam.getName());
            usersList.add(userSimpleInfoVo);
            userInfo.setCompanyId(ParamUtil.parseId(addUserItemParam.getCompanyId()));
            userInfo.setDeptId(ParamUtil.parseId(addUserItemParam.getDeptId()));
            userInfo.setPositionId(ParamUtil.parseId(addUserItemParam.getPositionId()));
            userInfo.setName(addUserItemParam.getName());
            userInfo.setSex(addUserItemParam.getSex());
            userInfo.setBirthday(addUserItemParam.getBirthday());
            userInfo.setPhoto(addUserItemParam.getPhoto());
            userInfo.setIsDel(0);
            userInfoList.add(userInfo);
            sb.append("“").append(addUserItemParam.getName()).append("”");

            //收集公司对应用户数量
            Long companyId=ParamUtil.parseId(addUserItemParam.getCompanyId());
            if (companyStatistics.containsKey(companyId)) {
                companyStatistics.put(companyId, companyStatistics.get(companyId) + 1);
            } else {
                companyStatistics.put(companyId, 1);
            }

            // 上传用户的人脸识别照片
            // 模拟服务接入成功 人脸服务
            Result result = reportFeign.uploadPhotoTemp(addUserItemParam.getPhoto(), userInfo.getUserId().toString(), userInfo.getName());
            if (!result.isSuccess()) {
                if (result.getCode() == ErrorCode.TPS_FILE_UPLOAD_FACE_NO_CORRECT_ERROR.getCode()) {
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_FACE_NO_CORRECT_ERROR);
                } else if (result.getCode() == ErrorCode.TPS_FILE_UPLOAD_ERROR.getCode()) {
                    throw new BizException(ErrorCode.TPS_FILE_UPLOAD_ERROR);
                }
            }
        });
        userInfoMapper.insertBatchSomeColumn(userInfoList);

        // 添加用户时，对应的 company info 的 all count 要 + userInfoList.size()
        companyStatistics.forEach((companyId, count) -> {
            CompanyInfo company = companyInfoMapper.selectCompanyInfoById(companyId);
            company.setAllCount(company.getAllCount() + count);
            companyInfoMapper.updateById(company);
        });
        // 记录日志
        AdminOperatingLog adminOperatingLog = new AdminOperatingLog();
        adminOperatingLog.setAccountId(accountId);
        adminOperatingLog.setContent(sb.toString());
        adminOperatingLog.setOperatingTime(LocalDateTime.now());
        adminOperatingLogMapper.insert(adminOperatingLog);

        return usersList;
    }

    @Override
    public UserDetailVo getUserDetail(Long accountId, Long userId) {
        // 是否拥有此用户的权限
        UserInfo userInfo = userInfoMapper.selectById(userId);
        if (userInfo == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ERROR_USER_NOT_EXISTS);
        }
        companyPermissionService.checkCompanyPermission(accountId, userInfo.getCompanyId());

        // 获得此用户的报告
        Result<UserDetailVo> result = reportFeign.getUserReportVoByUserId(new GetUserReportVoParam(userId.toString()));
        if (result == null || result.getCode() != 200 || !result.isSuccess()) {
            throw new BizException(ErrorCode.SYSTEM_ERROR);
        }
        return result.getData();
    }

    @Override
    public void exportUser(HttpServletResponse response, Long accountId, List<Long> companyIdList, List<Long> deptIdList, List<Long> positionIdList) {
        // 查询用户权限
        PermissionServiceImpl.PermissionList checked = permissionService
                .checkAndRefreshPermissionList(companyIdList, deptIdList, positionIdList, accountId);
        companyIdList = checked.companyIdList;
        deptIdList = checked.deptIdList;
        positionIdList = checked.positionIdList;

        // 查询用户信息
        List<UserInfoDto> userInfoDtoList = getUserList(companyIdList, deptIdList, positionIdList);
        try {
            int cnt = 1;
            for (UserInfoDto userInfoDto : userInfoDtoList) {
                userInfoDto.setAge(AgeUtils.getAge(userInfoDto.getBirthday()));
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                userInfoDto.setBirthdayStr(sdf.format(userInfoDto.getBirthday()));
                userInfoDto.setSerialNo(cnt++);
            }

            response.reset();
            String name = "人员信息列表.xlsx";
            String fileName = new String(name.getBytes("gb2312"), "ISO8859-1");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

            // 这里注册的 CustomCellWriteHandler工具类是用来在excel中适应内容自动调整表格宽度的
            ExcelWriter writer = EasyExcel.write(response.getOutputStream())
                    .registerWriteHandler(new CustomCellWriteHeightConfig())
                    .registerWriteHandler(new CustomCellWriteWeightConfig())
                    .registerWriteHandler(ExcelUtils.getCellStyle())
                    .build();
            WriteSheet sheet = EasyExcel.writerSheet(0, "人员信息列表").head(UserInfoDto.class).build();
            writer.write(userInfoDtoList, sheet);
            writer.finish();
        } catch (Exception e) {
            throw new BizException(ErrorCode.SYSTEM_ERROR_FILE_EXPORT_ERROR);
        }
    }

    @Override
    public ImportUserVo importUser(Long accountId, String excelMd5, String zipMd5) {
        File excel = fileService.getFileByMd5(excelMd5);
        String filePath = fileService.unZipByMd5(zipMd5);
        if (excel == null || filePath == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ERROR_FILE_NOT_EXISTS);
        }

        // 解析excel
        try {
            List<UserImportErrorVo> errorVoList = new ArrayList<>();
            EasyExcel.read(
                    excel,
                    UserInfoParam.class,
                    new UserInfoParamListener(
                            errorVoList,
                            adminOperatingLogMapper,
                            userInfoMapper,
                            companyInfoMapper,
                            deptInfoMapper,
                            positionInfoMapper,
                            companyPermissionService,
                            deptPermissionService,
                            fileService,
                            reportFeign,
                            accountId,
                            filePath
                    )
            ).sheet().doRead();
            // 将错误数据写入Excel
            File errorFile;
            String errorFileMd5 = null;
            if (!errorVoList.isEmpty()) {
                String errorFileName = fileService.getTempPathByType("xlsx") + File.separator + UUID.randomUUID() + ".xlsx";
                ExcelWriter writer = EasyExcel.write(errorFileName)
                        .registerWriteHandler(new CustomCellWriteHeightConfig())
                        .registerWriteHandler(new CustomCellWriteWeightConfig())
                        .registerWriteHandler(ExcelUtils.getCellStyle())
                        .build();
                WriteSheet sheet = EasyExcel.writerSheet(0, "错误数据")
                        .head(UserImportErrorVo.class)
                        .build();
                writer.write(errorVoList, sheet);
                writer.finish();
                // 获得excel文件
                errorFile = new File(errorFileName);
                // 计算md5
                errorFileMd5 = MD5Utils.fileToMD5(errorFileName);
                // 上传文件
                fileService.saveTempFile(errorFile, errorFileMd5, "xlsx");
            }

            ImportUserVo importUserVo = new ImportUserVo();
            importUserVo.setErrorFileMd5(errorFileMd5);
            importUserVo.setItem(errorVoList);
            // 删除zip和excel
            // fileService.deleteFileByMd5(excelMd5);
            // fileService.deleteFileByMd5(zipMd5);

            return importUserVo;

        } catch (Exception e) {
            throw new BizException(ErrorCode.SYSTEM_ERROR_EXCEL_PARSE_ERROR);
        }
    }

    @Override
    public void downloadTemplate(HttpServletResponse response) {
        try {
            response.reset();
            String name = "人员信息模板.xlsx";
            String fileName = new String(name.getBytes("gb2312"), "ISO8859-1");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

            ExcelWriter writer = EasyExcel.write(response.getOutputStream()).build();

            List<UserInfoParam> sample = getSample();

            // 添加合并单元格作为表头
            WriteSheet sheet = EasyExcel.writerSheet(0, "人员信息模板")
                    .head(UserInfoParam.class)
                    .registerWriteHandler(new CustomCellWriteHeightConfig())
                    .registerWriteHandler(new CustomCellWriteWeightConfig())
                    .build();
            writer.write(sample, sheet);
            writer.finish();
        } catch (Exception e) {
            throw new BizException(ErrorCode.SYSTEM_ERROR_FILE_EXPORT_ERROR);
        }
    }

    @Override
    public ReportSimpleInfoListVo getWarningReportList(Long accountId, Long userId, List<Integer> warningType, Integer page, Integer pageSize) {
        // 是否拥有此用户的权限
        UserInfo userInfo = userInfoMapper.selectById(userId);
        if (userInfo == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ERROR_USER_NOT_EXISTS);
        }

        CompanyInfo companyInfo = companyInfoMapper.selectById(userInfo.getCompanyId());
        if (companyInfo == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_COMPANY_NOT_EXISTS);
        }
        companyPermissionService.checkCompanyPermission(accountId, userInfo.getCompanyId());
        DeptInfo deptInfo = deptInfoMapper.selectById(userInfo.getDeptId());
        if (deptInfo == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_DEPT_NOT_EXISTS);
        }
        deptPermissionService.checkDeptPermission(accountId, userInfo.getDeptId());
        PositionInfo positionInfo = positionInfoMapper.selectById(userInfo.getPositionId());
        if (positionInfo == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_POSITION_NOT_EXISTS);
        }

        // 获得此用户的报告
        Result<ReportSimpleInfoListVo> result = reportFeign.getReportSimpleInfoVoListByUserId(
                new GetReportSimpleInfoVoListParam(userId.toString(),
                userInfo.getName(),
                companyInfo.getCompanyName(),
                deptInfo.getDeptName(),
                positionInfo.getPositionName(),
                warningType,
                page,
                pageSize)
        );
        if (result == null || result.getCode() != 200 || !result.isSuccess()) {
            throw new BizException(ErrorCode.SYSTEM_ERROR);
        }
        return result.getData();
    }

    private List<UserInfoVo> parseUserInfoListToVo(List<UserInfoDto> userInfoDtoList) {
        List<UserInfoVo> voList = new ArrayList<>();
        userInfoDtoList.forEach(userInfoDto -> voList.add(parseUserInfoDtoToVo(userInfoDto)));
        return voList;
    }

    private UserInfoVo parseUserInfoDtoToVo(UserInfoDto userInfoDto) {
        UserInfoVo vo = new UserInfoVo();
        vo.setUserId(userInfoDto.getUserId());
        vo.setCompanyId(userInfoDto.getCompanyId());
        vo.setCompanyName(userInfoDto.getCompanyName());
        vo.setDeptId(userInfoDto.getDeptId());
        vo.setDeptName(userInfoDto.getDeptName());
        vo.setPositionId(userInfoDto.getPositionId());
        vo.setPositionName(userInfoDto.getPositionName());
        vo.setName(userInfoDto.getName());
        vo.setSex(userInfoDto.getSex());
        vo.setAge(AgeUtils.getAge(userInfoDto.getBirthday()));
        vo.setBirthday(userInfoDto.getBirthday());
        vo.setPhoto(userInfoDto.getPhoto());
        return vo;
    }
}
